from django.shortcuts import render, get_object_or_404
from django.http import JsonResponse, HttpResponse, Http404
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from django.contrib.auth.decorators import login_required
from django.core.files.storage import default_storage
from django.conf import settings
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
import json
import os
import tempfile
import logging
from typing import Dict, Any

from apps.core.models import Template, ProcessingTask, UploadedFile
from .processor import ExcelProcessor
from .serializers import ProcessingRequestSerializer, ProcessingResultSerializer

logger = logging.getLogger(__name__)


class ExcelProcessorViewSet(viewsets.ViewSet):
    """Excel处理器API视图集"""
    
    permission_classes = [IsAuthenticated]
    
    @action(detail=False, methods=['post'])
    def process_files(self, request):
        """
        处理文件API
        
        POST /api/excel-processor/process_files/
        {
            "template_id": 1,
            "source_file_ids": [1, 2, 3],
            "task_name": "测试任务",
            "options": {
                "group_by": "POL",
                "output_format": "xlsx"
            }
        }
        """
        try:
            serializer = ProcessingRequestSerializer(data=request.data)
            if not serializer.is_valid():
                return Response({
                    'success': False,
                    'error': '请求参数无效',
                    'details': serializer.errors
                }, status=status.HTTP_400_BAD_REQUEST)
            
            data = serializer.validated_data
            
            # 获取模板
            template = get_object_or_404(Template, id=data['template_id'], is_active=True)
            
            # 获取源文件
            source_files = UploadedFile.objects.filter(
                id__in=data['source_file_ids'],
                file_type='source'
            )
            
            if not source_files.exists():
                return Response({
                    'success': False,
                    'error': '未找到有效的源文件'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 创建处理任务
            task = ProcessingTask.objects.create(
                task_name=data.get('task_name', f'处理任务_{template.name}'),
                template=template,
                status='pending',
                input_files={
                    'source_files': [f.id for f in source_files],
                    'template_file': template.id
                }
            )
            
            # 异步处理文件
            result = self._process_files_async(task, template, source_files, data.get('options', {}))
            
            return Response({
                'success': True,
                'task_id': task.id,
                'message': '文件处理已开始',
                'result': result
            })
            
        except Exception as e:
            logger.error(f"处理文件API失败: {str(e)}", exc_info=True)
            return Response({
                'success': False,
                'error': f'处理失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    def _process_files_async(self, task: ProcessingTask, template: Template, 
                           source_files, options: Dict[str, Any]) -> Dict[str, Any]:
        """
        异步处理文件
        
        Args:
            task: 处理任务
            template: 模板
            source_files: 源文件查询集
            options: 处理选项
            
        Returns:
            处理结果
        """
        try:
            # 更新任务状态
            task.status = 'processing'
            task.progress = 10
            task.save()
            
            # 准备文件路径
            source_file_paths = []
            for file_obj in source_files:
                file_path = file_obj.file.path
                if os.path.exists(file_path):
                    source_file_paths.append(file_path)
            
            if not source_file_paths:
                raise Exception("没有找到有效的源文件路径")
            
            # 模板文件路径
            template_file_path = template.template_file.path
            if not os.path.exists(template_file_path):
                raise Exception("模板文件不存在")
            
            task.progress = 30
            task.save()
            
            # 创建输出目录
            output_dir = os.path.join(
                settings.MEDIA_ROOT, 'generated', f'task_{task.id}'
            )
            os.makedirs(output_dir, exist_ok=True)
            
            # 准备模板配置
            template_config = {
                'mapping_config': template.mapping_config or {},
                'fixed_config': template.fixed_config or {},
                'pol_config': template.pol_config or {},
                'shipper_config': template.shipper_config or {}
            }
            
            task.progress = 50
            task.save()
            
            # 创建处理器并处理文件
            processor = ExcelProcessor(template_config)
            result = processor.process_files(
                source_files=source_file_paths,
                template_file=template_file_path,
                output_dir=output_dir,
                task_name=task.task_name
            )
            
            task.progress = 90
            task.save()
            
            if result['success']:
                # 更新任务结果
                task.status = 'completed'
                task.progress = 100
                task.result_files = {
                    'files': [os.path.basename(f) for f in result['generated_files']],
                    'zip_file': os.path.basename(result['zip_file']) if result.get('zip_file') else None,
                    'output_dir': output_dir
                }
                task.save()
                
                logger.info(f"任务 {task.id} 处理完成")
                return result
            else:
                # 处理失败
                task.status = 'failed'
                task.error_message = result.get('error', '未知错误')
                task.save()
                
                logger.error(f"任务 {task.id} 处理失败: {task.error_message}")
                return result
                
        except Exception as e:
            # 更新任务状态为失败
            task.status = 'failed'
            task.error_message = str(e)
            task.save()
            
            logger.error(f"任务 {task.id} 处理异常: {str(e)}", exc_info=True)
            return {
                'success': False,
                'error': str(e)
            }
    
    @action(detail=False, methods=['get'])
    def task_status(self, request):
        """
        获取任务状态
        
        GET /api/excel-processor/task_status/?task_id=1
        """
        task_id = request.query_params.get('task_id')
        if not task_id:
            return Response({
                'success': False,
                'error': '缺少task_id参数'
            }, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            task = get_object_or_404(ProcessingTask, id=task_id)
            
            return Response({
                'success': True,
                'task': {
                    'id': task.id,
                    'task_name': task.task_name,
                    'status': task.status,
                    'progress': task.progress,
                    'created_at': task.created_at,
                    'started_at': task.started_at,
                    'completed_at': task.completed_at,
                    'error_message': task.error_message,
                    'result_files': task.result_files
                }
            })
            
        except Exception as e:
            return Response({
                'success': False,
                'error': str(e)
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    @action(detail=False, methods=['post'])
    def validate_template(self, request):
        """
        验证模板配置
        
        POST /api/excel-processor/validate_template/
        {
            "template_id": 1
        }
        """
        template_id = request.data.get('template_id')
        if not template_id:
            return Response({
                'success': False,
                'error': '缺少template_id参数'
            }, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            template = get_object_or_404(Template, id=template_id)
            
            # 准备配置
            config = {
                'mapping_config': template.mapping_config or {},
                'fixed_config': template.fixed_config or {},
                'pol_config': template.pol_config or {},
                'shipper_config': template.shipper_config or {}
            }
            
            # 验证配置
            is_valid, message = ExcelProcessor.validate_template_config(config)
            
            return Response({
                'success': True,
                'is_valid': is_valid,
                'message': message,
                'config_summary': {
                    'mapping_rules': len(config['mapping_config']),
                    'fixed_values': len(config['fixed_config']),
                    'pol_mappings': len(config['pol_config']),
                    'shipper_mappings': len(config['shipper_config'])
                }
            })
            
        except Exception as e:
            return Response({
                'success': False,
                'error': str(e)
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    @action(detail=False, methods=['post'])
    def preview_file(self, request):
        """
        预览文件内容
        
        POST /api/excel-processor/preview_file/
        {
            "file_id": 1,
            "max_rows": 10
        }
        """
        file_id = request.data.get('file_id')
        max_rows = request.data.get('max_rows', 10)
        
        if not file_id:
            return Response({
                'success': False,
                'error': '缺少file_id参数'
            }, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            file_obj = get_object_or_404(UploadedFile, id=file_id)
            file_path = file_obj.file.path
            
            if not os.path.exists(file_path):
                return Response({
                    'success': False,
                    'error': '文件不存在'
                }, status=status.HTTP_404_NOT_FOUND)
            
            # 获取文件信息
            file_info = ExcelProcessor.get_file_info(file_path)
            
            # 读取文件内容预览
            preview_data = self._get_file_preview(file_path, max_rows)
            
            return Response({
                'success': True,
                'file_info': file_info,
                'preview': preview_data
            })
            
        except Exception as e:
            return Response({
                'success': False,
                'error': str(e)
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    def _get_file_preview(self, file_path: str, max_rows: int = 10) -> Dict[str, Any]:
        """
        获取文件预览数据
        
        Args:
            file_path: 文件路径
            max_rows: 最大行数
            
        Returns:
            预览数据
        """
        try:
            import pandas as pd
            
            file_ext = os.path.splitext(file_path)[1].lower()
            
            if file_ext in ['.xlsx', '.xls']:
                df = pd.read_excel(file_path, nrows=max_rows)
            elif file_ext == '.csv':
                df = pd.read_csv(file_path, nrows=max_rows, encoding='utf-8')
            else:
                return {'error': '不支持的文件格式'}
            
            return {
                'columns': df.columns.tolist(),
                'data': df.to_dict('records'),
                'total_rows': len(df),
                'total_columns': len(df.columns)
            }
            
        except Exception as e:
            return {'error': str(e)}


@csrf_exempt
@require_http_methods(["POST"])
def ajax_process_files(request):
    """
    AJAX处理文件接口
    """
    try:
        data = json.loads(request.body)
        
        template_id = data.get('template_id')
        source_file_ids = data.get('source_file_ids', [])
        task_name = data.get('task_name', '处理任务')
        
        if not template_id or not source_file_ids:
            return JsonResponse({
                'success': False,
                'error': '缺少必要参数'
            })
        
        # 获取模板和文件
        template = get_object_or_404(Template, id=template_id, is_active=True)
        source_files = UploadedFile.objects.filter(
            id__in=source_file_ids,
            file_type='source'
        )
        
        if not source_files.exists():
            return JsonResponse({
                'success': False,
                'error': '未找到有效的源文件'
            })
        
        # 创建处理任务
        task = ProcessingTask.objects.create(
            task_name=task_name,
            template=template,
            status='pending'
        )
        
        return JsonResponse({
            'success': True,
            'task_id': task.id,
            'message': '任务创建成功，开始处理...'
        })
        
    except Exception as e:
        logger.error(f"AJAX处理文件失败: {str(e)}", exc_info=True)
        return JsonResponse({
            'success': False,
            'error': str(e)
        })


@require_http_methods(["GET"])
def ajax_task_progress(request):
    """
    AJAX获取任务进度
    """
    task_id = request.GET.get('task_id')
    if not task_id:
        return JsonResponse({
            'success': False,
            'error': '缺少task_id参数'
        })
    
    try:
        task = get_object_or_404(ProcessingTask, id=task_id)
        
        return JsonResponse({
            'success': True,
            'task': {
                'id': task.id,
                'status': task.status,
                'progress': task.progress,
                'error_message': task.error_message,
                'result_files': task.result_files
            }
        })
        
    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': str(e)
        })


@require_http_methods(["GET"])
def download_result_files(request, task_id):
    """
    下载处理结果文件
    """
    try:
        task = get_object_or_404(ProcessingTask, id=task_id)
        
        if task.status != 'completed' or not task.result_files:
            raise Http404("任务未完成或无结果文件")
        
        # 获取压缩包路径
        zip_file = task.result_files.get('zip_file')
        output_dir = task.result_files.get('output_dir')
        
        if not zip_file or not output_dir:
            raise Http404("结果文件不存在")
        
        zip_path = os.path.join(output_dir, zip_file)
        
        if not os.path.exists(zip_path):
            raise Http404("压缩包文件不存在")
        
        # 返回文件下载响应
        with open(zip_path, 'rb') as f:
            response = HttpResponse(f.read(), content_type='application/zip')
            response['Content-Disposition'] = f'attachment; filename="{zip_file}"'
            return response
            
    except Exception as e:
        logger.error(f"下载结果文件失败: {str(e)}")
        raise Http404("文件下载失败")


def processor_status(request):
    """
    处理器状态页面
    """
    # 获取最近的处理任务
    recent_tasks = ProcessingTask.objects.order_by('-created_at')[:10]
    
    # 统计信息
    stats = {
        'total_tasks': ProcessingTask.objects.count(),
        'completed_tasks': ProcessingTask.objects.filter(status='completed').count(),
        'failed_tasks': ProcessingTask.objects.filter(status='failed').count(),
        'processing_tasks': ProcessingTask.objects.filter(status='processing').count(),
    }
    
    context = {
        'recent_tasks': recent_tasks,
        'stats': stats
    }
    
    return render(request, 'excel_processor/status.html', context)